﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Elderos.Controls;
using FontDialogSample;
using Microsoft.Samples.CustomControls;
using TreeBuilder.Settings;

namespace TreeBuilder
{
    /// <summary>
    /// Interaction logic for OptionsWindow.xaml
    /// </summary>
    public partial class OptionsWindow : Window
    {
        public FontChooser NodeFontDlg;
        public FontChooser UpperIndexFontDlg;
        public FontChooser LowerIndexFontDlg;

        public OptionsWindow()
        {
            InitializeComponent();

            InitializeGeneralTab(ApplicationSettings.Default.CheckUpdates);

            InitializeFontDlg(ref NodeFontDlg, NodeFontSample,
                new SolidColorBrush(NodeSettings.Default.FontColor),
                NodeSettings.Default.FontFamily ?? FontFamily,
                NodeSettings.Default.FontSize,
                NodeSettings.Default.FontStretch,
                NodeSettings.Default.FontStyle,
                NodeSettings.Default.FontWeight,
                NodeSettings.Default.TextDecorations
                );

            InitializeFrameTab(
                FrameSettings.Default.Brush,
                FrameSettings.Default.Thickness,
                FrameSettings.Default.DashStyle
                );

            InitializeFontDlg(ref UpperIndexFontDlg, UpperIndexSample,
                new SolidColorBrush(IndexSettings.Default.UpperFontColor),
                IndexSettings.Default.UpperFontFamily ?? FontFamily,
                IndexSettings.Default.UpperFontSize,
                IndexSettings.Default.UpperFontStretch,
                IndexSettings.Default.UpperFontStyle,
                IndexSettings.Default.UpperFontWeight,
                IndexSettings.Default.UpperTextDecorations
                );

            InitializeFontDlg(ref LowerIndexFontDlg, LowerIndexSample,
                new SolidColorBrush(IndexSettings.Default.LowerFontColor),
                IndexSettings.Default.LowerFontFamily ?? FontFamily,
                IndexSettings.Default.LowerFontSize,
                IndexSettings.Default.LowerFontStretch,
                IndexSettings.Default.LowerFontStyle,
                IndexSettings.Default.LowerFontWeight,
                IndexSettings.Default.LowerTextDecorations
                );

            InitializeLineTab(new SolidColorBrush(LineSettings.Default.Stroke),
                LineSettings.Default.DashStyle,
                LineSettings.Default.Thickness
                );

            InitializeArrowTab(
                new SolidColorBrush(ArrowSettings.Default.Stroke),
                ArrowSettings.Default.DashStyle,
                ArrowSettings.Default.Thickness,
                ArrowSettings.Default.VerticalOffset
                );

            InitializeTrianglesTab(
                new SolidColorBrush(TriangleSettings.Default.Stroke),
                TriangleSettings.Default.DashStyle,
                TriangleSettings.Default.Thickness
                );

            InitializeImageTab(
                ImageSettings.Default.FrameThickness,
                ImageSettings.Default.DpiX,
                ImageSettings.Default.DpiY
                );
        }

        private void InitializeGeneralTab(bool checkUpdates)
        {
            CheckUpdatesCheckBox.IsChecked = checkUpdates;
        }

        private void InitializeFrameTab(Brush brush, double thickness, DoubleCollection dashStyle)
        {
            FrameColorPicker.SelectedColor = ((SolidColorBrush)brush).Color;
            FrameThicknessBox.Text = thickness.ToString();
            FrameDashesBox.Text = dashStyle == null ? "" : dashStyle.ToString();
        }

        private void InitializeImageTab(Thickness frameThickness, double dpiX, double dpiY)
        {
            FrameMarginLeftBox.Text = frameThickness.Left.ToString();
            FrameMarginTopBox.Text = frameThickness.Top.ToString();
            FrameMarginRightBox.Text = frameThickness.Right.ToString();
            FrameMarginBottomBox.Text = frameThickness.Bottom.ToString();
            ImageDpiXBox.Text = dpiX.ToString();
            ImageDpiYBox.Text = dpiY.ToString();
        }

        private void InitializeLineTab(Brush brush, DoubleCollection dashes, double thickness)
        {
            LineColorPicker.SelectedColor = ((SolidColorBrush)brush).Color;
            LineDashesBox.Text = dashes == null ? "" : dashes.ToString();
            LineThicknessBox.Text = thickness.ToString();
        }

        private void InitializeArrowTab(Brush brush, DoubleCollection dashes, double thickness,
            double verticalOffset
            )
        {
            ArrowColorPicker.SelectedColor = ((SolidColorBrush)brush).Color;
            ArrowDashesBox.Text = dashes == null ? "" : dashes.ToString();
            ArrowThicknessBox.Text = thickness.ToString();
            ArrowVerticalOffsetBox.Text = verticalOffset.ToString();
        }

        private void InitializeTrianglesTab(Brush brush, DoubleCollection dashes, double thickness)
        {
            TriangleColorPicker.SelectedColor = ((SolidColorBrush)brush).Color;
            TriangleDashesBox.Text = dashes == null ? "" : dashes.ToString();
            TriangleThicknessBox.Text = thickness.ToString();
        }

        private void InitializeFontDlg(ref FontChooser dlg, Paragraph sample, Brush fontColor, FontFamily fontFamily, double fontSize, 
            FontStretch fontStretch, FontStyle fontStyle, FontWeight fontWeight, TextDecorationCollection textDecorations)
        {
            dlg = new FontChooser();
            Font.ApplyFont(dlg, fontColor, fontFamily, fontSize, fontStretch, fontStyle, fontWeight, textDecorations);
            Font.ApplyFont(dlg, sample);
        }

        private bool ValidateDouble(string arg)
        {
            return ValidatableTextBox.ValidateDouble(arg);
        }

        private bool ValidateMarginSide(string arg)
        {
            if (!ValidatableTextBox.ValidateDouble(arg)) return false;
            double value;
            if (!double.TryParse(arg.Replace(",", "."), NumberStyles.Number, CultureInfo.InvariantCulture, out value))
                return false;

            return value <= ApplicationSettings.Default.MaxFrameThickness
                && value >= ApplicationSettings.Default.MinFrameThickness;
        }

        private bool ValidateDoubleCollection(string arg)
        {
            return ValidatableTextBox.ValidateDoubleCollection(arg);
        }

        private void NodeFontButton_Click(object sender, RoutedEventArgs e)
        {
            var dlg = new FontChooser();
            dlg.Owner = this;
            Font.ApplyFont(NodeFontDlg, dlg);

            if (!dlg.ShowDialog().Value) return;

            InitializeFontDlg(ref NodeFontDlg, NodeFontSample, dlg.SelectedFontColor, dlg.SelectedFontFamily, dlg.SelectedFontSize,
                              dlg.SelectedFontStretch, dlg.SelectedFontStyle, dlg.SelectedFontWeight,
                              dlg.SelectedTextDecorations);
        }

        public void ApplySettings()
        {
            ApplyGeneralSettings();
            ApplyImageSettings();
            ApplyNodeSettings();
            ApplyFrameSettings();
            ApplyLineSettings();
            ApplyArrowSettings();
            ApplyTriangleSettings();
            ApplyIndexSettings();
        }

        private void ApplyGeneralSettings()
        {
            ApplicationSettings.Default.CheckUpdates = CheckUpdatesCheckBox.IsChecked.Value;
        }

        private void ApplyFrameSettings()
        {
            FrameSettings.Default.Brush = new SolidColorBrush(FrameColorPicker.SelectedColor);
            if (LineThicknessBox.Text.Length > 0)
                FrameSettings.Default.Thickness = double.Parse(FrameThicknessBox.Text.Replace(",", "."),
                                                                     CultureInfo.InvariantCulture);
            FrameSettings.Default.DashStyle = DoubleCollection.Parse(FrameDashesBox.Text.Replace(",", "."));

            FrameSettings.Default.Save();
        }

        private void ApplyIndexSettings()
        {
            IndexSettings.Default.UpperFontColor = (UpperIndexFontDlg.SelectedFontColor as SolidColorBrush).Color;
            IndexSettings.Default.UpperFontFamily = UpperIndexFontDlg.SelectedFontFamily;
            IndexSettings.Default.UpperFontSize = UpperIndexFontDlg.SelectedFontSize;
            IndexSettings.Default.UpperFontStretch = UpperIndexFontDlg.SelectedFontStretch;
            IndexSettings.Default.UpperFontStyle = UpperIndexFontDlg.SelectedFontStyle;
            IndexSettings.Default.UpperFontWeight = UpperIndexFontDlg.SelectedFontWeight;
            IndexSettings.Default.UpperTextDecorations = UpperIndexFontDlg.SelectedTextDecorations.Clone();

            IndexSettings.Default.LowerFontColor = (LowerIndexFontDlg.SelectedFontColor as SolidColorBrush).Color;
            IndexSettings.Default.LowerFontFamily = LowerIndexFontDlg.SelectedFontFamily;
            IndexSettings.Default.LowerFontSize = LowerIndexFontDlg.SelectedFontSize;
            IndexSettings.Default.LowerFontStretch = LowerIndexFontDlg.SelectedFontStretch;
            IndexSettings.Default.LowerFontStyle = LowerIndexFontDlg.SelectedFontStyle;
            IndexSettings.Default.LowerFontWeight = LowerIndexFontDlg.SelectedFontWeight;
            IndexSettings.Default.LowerTextDecorations = LowerIndexFontDlg.SelectedTextDecorations.Clone();

            IndexSettings.Default.Save();
        }

        private void ApplyTriangleSettings()
        {
            if (LineThicknessBox.Text.Length > 0)
                TriangleSettings.Default.Thickness = double.Parse(TriangleThicknessBox.Text.Replace(",", "."),
                                                                     CultureInfo.InvariantCulture);
            TriangleSettings.Default.DashStyle = DoubleCollection.Parse(TriangleDashesBox.Text.Replace(",", "."));
            TriangleSettings.Default.Stroke = TriangleColorPicker.SelectedColor;

            TriangleSettings.Default.Save();
        }

        private void ApplyArrowSettings()
        {
            if (ArrowThicknessBox.Text.Length > 0)
                ArrowSettings.Default.Thickness = double.Parse(ArrowThicknessBox.Text.Replace(",", "."),
                                                               CultureInfo.InvariantCulture);
            ArrowSettings.Default.DashStyle = DoubleCollection.Parse(ArrowDashesBox.Text.Replace(",", "."));
            ArrowSettings.Default.Stroke = ArrowColorPicker.SelectedColor;

            if (ArrowVerticalOffsetBox.Text.Length > 0)
                ArrowSettings.Default.VerticalOffset = double.Parse(ArrowVerticalOffsetBox.Text.Replace(",", "."),
                                                                    CultureInfo.InvariantCulture);

            ArrowSettings.Default.Save();
        }

        private void ApplyLineSettings()
        {
            if (LineThicknessBox.Text.Length > 0)
                LineSettings.Default.Thickness = double.Parse(LineThicknessBox.Text.Replace(",", "."),
                                                                     CultureInfo.InvariantCulture);
            LineSettings.Default.DashStyle = DoubleCollection.Parse(LineDashesBox.Text.Replace(",", "."));
            LineSettings.Default.Stroke = LineColorPicker.SelectedColor;

            LineSettings.Default.Save();
        }

        private void ApplyNodeSettings()
        {
            NodeSettings.Default.FontColor = (NodeFontDlg.SelectedFontColor as SolidColorBrush).Color;
            NodeSettings.Default.FontFamily = NodeFontDlg.SelectedFontFamily;
            NodeSettings.Default.FontSize = NodeFontDlg.SelectedFontSize;
            NodeSettings.Default.FontStretch = NodeFontDlg.SelectedFontStretch;
            NodeSettings.Default.FontStyle = NodeFontDlg.SelectedFontStyle;
            NodeSettings.Default.FontWeight = NodeFontDlg.SelectedFontWeight;
            NodeSettings.Default.TextDecorations = NodeFontDlg.SelectedTextDecorations.Clone();

            NodeSettings.Default.Save();
        }

        private void ApplyImageSettings()
        {
            double left = double.Parse(FrameMarginLeftBox.Value);
            double top = double.Parse(FrameMarginTopBox.Value);
            double right = double.Parse(FrameMarginRightBox.Value);
            double bottom = double.Parse(FrameMarginBottomBox.Value);
            ImageSettings.Default.FrameThickness = new Thickness(left, top, right, bottom);

            double dpiX = double.Parse(ImageDpiXBox.Value);
            double dpiY = double.Parse(ImageDpiYBox.Value);
            ImageSettings.Default.DpiX = dpiX;
            ImageSettings.Default.DpiY = dpiY;

            ImageSettings.Default.Save();
        }

        private void OkButton_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
            Close();
        }

        private void ApplyButton_Click(object sender, RoutedEventArgs e)
        {
            ApplySettings();
        }

        private bool ValidateVerticalOffset(string arg)
        {
            if (!ValidatableTextBox.ValidateDouble(arg)) return false;

            double value;
            if (!double.TryParse(arg.Replace(",", "."), NumberStyles.Number, CultureInfo.InvariantCulture, out value))
                return false;
            return value <= ApplicationSettings.Default.MaxVerticalOffset
                && value >= ApplicationSettings.Default.MinVerticalOffset;
        }

        private void UpperIndexFontButton_Click(object sender, RoutedEventArgs e)
        {
            var dlg = new FontChooser();
            dlg.Owner = this;
            Font.ApplyFont(UpperIndexFontDlg, dlg);

            if (!dlg.ShowDialog().Value) return;

            InitializeFontDlg(ref UpperIndexFontDlg, UpperIndexSample, dlg.SelectedFontColor, dlg.SelectedFontFamily, dlg.SelectedFontSize,
                              dlg.SelectedFontStretch, dlg.SelectedFontStyle, dlg.SelectedFontWeight,
                              dlg.SelectedTextDecorations);
        }

        private void LowerIndexFontButton_Click(object sender, RoutedEventArgs e)
        {
            var dlg = new FontChooser();
            dlg.Owner = this;
            Font.ApplyFont(LowerIndexFontDlg, dlg);

            if (!dlg.ShowDialog().Value) return;

            InitializeFontDlg(ref LowerIndexFontDlg, LowerIndexSample, dlg.SelectedFontColor, dlg.SelectedFontFamily, dlg.SelectedFontSize,
                              dlg.SelectedFontStretch, dlg.SelectedFontStyle, dlg.SelectedFontWeight,
                              dlg.SelectedTextDecorations);
        }

        private bool ValidateDpi(string arg)
        {
            if (!ValidatableTextBox.ValidateDouble(arg)) return false;
            double value;
            if (!double.TryParse(arg.Replace(",", "."), NumberStyles.Number, CultureInfo.InvariantCulture, out value))
                return false;

            return value >= ApplicationSettings.Default.MinDpi && value <= ApplicationSettings.Default.MaxDpi;
        }

        private bool ValidateThickness(string arg)
        {
            if (!ValidatableTextBox.ValidateDouble(arg)) return false;
            double value;
            if (!double.TryParse(arg.Replace(",", "."), NumberStyles.Number, CultureInfo.InvariantCulture, out value))
                return false;

            return value <= ApplicationSettings.Default.MaxBinderThickness && value >= ApplicationSettings.Default.MinBinderThickness;
        }

        private bool ParseDoubleCollection(string arg)
        {
            return ValidatableTextBox.ParseDoubleCollection(arg);
        }
    }
}
